package com.distortiongames.level27.math
{

	public class Vector2D

	{
		public var x:Number;
		public var y:Number;

		public function Vector2D(x:Number=0, y:Number=0)
		{
			this.x=x;
			this.y=y;
		}

		public function copy():Vector2D
		{
			return new Vector2D(x, y);
		}

		public function add(vector:Vector2D):void
		{
			this.x+=vector.x;
			this.y+=vector.y;
		}

		public function added(vector:Vector2D):Vector2D
		{
			return new Vector2D(this.x + vector.x, this.y + vector.y);
		}

		public function subtract(vector:Vector2D):void
		{
			this.x-=vector.x;
			this.y-=vector.y;
		}

		public function subtracted(vector:Vector2D):Vector2D
		{
			return new Vector2D(this.x - vector.x, this.y - vector.y);
		}

		public function scale(scalar:Number):void
		{
			this.x*=scalar;
			this.y*=scalar;
		}

		public function scaled(scalar:Number):Vector2D
		{
			return new Vector2D(this.x * scalar, this.y * scalar);
		}

		public function divide(scalar:Number):void
		{
			this.x/=scalar;
			this.y/=scalar;
		}

		public function divided(scalar:Number):Vector2D
		{
			return new Vector2D(this.x / scalar, this.y / scalar);
		}

		public function magnitude():Number
		{
			return Math.sqrt((x * x) + (y * y));
		}

		public function squareMagnitude():Number
		{
			return (x * x) + (y * y);
		}

		public function setMagnitude(mag:Number):void
		{
			scale(mag / magnitude());
		}

		public function angle():Number
		{
			var a:Number=Math.atan2(y, x);
			if (a < 0)
			{
				a+=Math.PI * 2;
				if (a == Math.PI * 2)
					a=0;
				return a;
			}
			else
			{
				return a;
			}
		}

		public function rotate(deltaAngle:Number):void
		{
			var x:Number=this.x;
			var y:Number=this.y;
			this.x=x * Math.cos(deltaAngle) - y * Math.sin(deltaAngle);
			this.y=x * Math.sin(deltaAngle) + y * Math.cos(deltaAngle);
		}

		public function rotated(deltaAngle:Number):Vector2D
		{
			return new Vector2D(x * Math.cos(deltaAngle) - y * Math.sin(deltaAngle), x * Math.sin(deltaAngle) + y * Math.cos(deltaAngle));
		}

		public function rotateAround(vector:Vector2D, deltaAngle:Number) : void
		{
			subtract(vector);
			rotate(deltaAngle);
			add(vector);
		}

		public function rotatedAround(vector : Vector2D, deltaAngle:Number) : Vector2D
		{
			var result:Vector2D = copy();
			result.subtract(vector);
			result.rotate(deltaAngle);
			result.add(vector);
			return result;
		}

		public function flip():void
		{
			this.x*=-1;
			this.y*=-1;
		}

		public function flipped():Vector2D
		{
			return new Vector2D(this.x * -1, this.y * -1);
		}

		public function normalize():void
		{
			var mag:Number = magnitude();
			if (mag != 0)
				divide(mag);
		}

		public function normalized():Vector2D
		{
			var mag:Number = magnitude();
			if (mag != 0) return new Vector2D(this.x /mag, this.y /mag);
			else return new Vector2D(this.x, this.y);
		}

		public function perpendicular() : Vector2D {
			return new Vector2D(-this.x, this.y);
		}

		public static function distance(vector1:Vector2D, vector2:Vector2D):Number
		{
			var dx:Number=vector1.x - vector2.x;
			var dy:Number=vector1.y - vector2.y;
			return Math.sqrt(dx * dx + dy * dy);
		}

		public static function dot(vector1:Vector2D, vector2:Vector2D):Number
		{
			var dot:Number=vector1.x * vector2.x + vector1.y * vector2.y;
			return dot;
		}

		public static function lerp(begin:Vector2D, end:Vector2D, interpolator:Number):Vector2D
		{
			return new Vector2D((end.x - begin.x) * interpolator + begin.x, (end.y - begin.y) * interpolator + begin.y);
		}

		public function toString():String
		{
			return "[" + x.toPrecision(3) + ", " + y.toPrecision(3) + "]";
		}
	}
}

